package com.geek.novel.network

import android.graphics.BitmapFactory
import android.text.TextUtils
import com.geek.novel.common.Constant
import com.geek.novel.utils.GsonUtil
import com.geek.novel.utils.LogCatUtil
import com.geek.novel.utils.SecurityUtil
import com.geek.novel.utils.ToastUtils
import com.geek.novel.view.loading.LoadingDialogUtil
import com.geek.novel.vo.ApiErrorResult
import com.geek.novel.vo.ApiResult
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import io.reactivex.Observer
import io.reactivex.disposables.Disposable
import okhttp3.ResponseBody
import retrofit2.HttpException


/**
 * 请求的结果处理
 * Created by  on 2022/05/29
 */
abstract class HttpResult<T, E>(private var cls: Class<T>, var type: Int, var name: String? = "data") : Observer<E> {

    override fun onNext(response: E) {
        try {
            val result = ApiResult()

            if(response is ResponseBody){
                val bys = response.bytes()
                if(type == Constant.HTTP_RESULT_TYPE_IMAGE){
                    val bitmap = BitmapFactory.decodeByteArray(bys, 0, bys.size)
                    result.result = bitmap
                }
                handleSuccess(result)
                return
            }

            val jsonObject: JsonObject = response as JsonObject
            LogCatUtil.d("===response=", "==response=${response}")
            val respCode = jsonObject.get("status").asInt
            val message = jsonObject.get("message").asString
            result.code = respCode
            when (respCode) {
                200 -> {//请求成功
                    result.isResult = true
                    var element = jsonObject as JsonElement
                    if(!TextUtils.isEmpty(name)){
                        element = jsonObject.get(name)
                    }
                    result.content = element.toString()

                    //处理数组的情况
                    if(type == Constant.HTTP_RESULT_TYPE_LIST){
                        result.resultList = element.asJsonArray
                    }else{
                        result.result = GsonUtil.fromJson(element, cls)
                    }
                    handleSuccess(result)
                }
                400 -> {//校验异常
                    val error = GsonUtil.fromJson(jsonObject, ApiErrorResult::class.java)
                    onHandleWarning(error)
                }
                401 -> {//Token过期
                    loginTimeout()
                    handleLogout()
                }
                else -> {
                    val error = GsonUtil.fromJson(jsonObject, ApiErrorResult::class.java)
                    onHandleError(error)
                }
            }
        } catch (e: Exception) {
            this.onError(e)
        }

    }

    override fun onSubscribe(d: Disposable) {
        DisposableManager.instance.add(d)
    }

    /**错误信息处理*/
    override fun onError(err: Throwable) {
        //隐藏loading弹框
        LoadingDialogUtil.getInstance().dismiss()
        //处理http异常
        if(err is HttpException){
            when(err.code()){
                401 -> {//Token过期
                    loginTimeout()
                    handleLogout()
                }
                else -> {
                    val response = err.response()!!
                    val errJson = response.errorBody()!!.string()
                    val result = GsonUtil.fromJson(errJson, ApiErrorResult::class.java)
                    handleError(result)
                }
            }
            return
        }
        //其他异常处理
        val errMessage = err.message
        LogCatUtil.e("HttpResult", "$errMessage", err)
        ToastUtils.toast("请求失败：$errMessage")
    }

    override fun onComplete() {
        //隐藏loading弹框
        LoadingDialogUtil.getInstance().dismiss()
    }

    abstract fun handleSuccess(result: ApiResult)
    abstract fun handleError(err: ApiErrorResult)
    abstract fun handleLogout()

    /**处理警告信息*/
    open fun onHandleWarning(err: ApiErrorResult){
        ToastUtils.toast(err.message)
        this.handleError(err)
    }

    /**处理警告信息*/
    open fun onHandleError(err: ApiErrorResult){
        ToastUtils.toast(err.message)
        this.handleError(err)
    }

    /**
     * 登录超时
     */
    private fun loginTimeout() {
        // 登录超时, 清除用户信息
        SecurityUtil.logout()
    }

}